// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Author: wsfuyibing <682805@qq.com>
// Date: 2024-07-23

package results

import (
	"fmt"
	"gitee.com/go-libs/result/src"
)

type ErrnoResult struct {
	htm, str bool

	Data     any          `json:"data,omitempty" xml:"data,omitempty"`
	DataType src.DataType `json:"type" xml:"type"`
	Errno    int          `json:"errno" xml:"errno"`
	Error    string       `json:"error" xml:"error"`
}

const (
	errnoSuccess     = 0
	errnoSuccessText = "success"
)

func NewErrno() src.Result { return &ErrnoResult{} }

func (o *ErrnoResult) IsHtml() bool { return o.htm }

func (o *ErrnoResult) IsString() bool { return o.str }

func (o *ErrnoResult) String() string {
	if o.str || o.htm {
		return fmt.Sprintf(`%s`, o.Data)
	}
	return src.ToJSON(o)
}

func (o *ErrnoResult) With(data any) src.Result {
	o.str, o.htm = false, false
	o.Data = data
	o.DataType = src.DataTypeObject
	o.Errno = errnoSuccess
	o.Error = errnoSuccessText
	return o
}

func (o *ErrnoResult) WithCodeError(code int, message string) src.Result {
	o.str, o.htm = false, false
	o.Data = nil
	o.DataType = src.DataTypeError
	o.Errno = code
	o.Error = message
	return o
}

func (o *ErrnoResult) WithEmpty() src.Result {
	return o.With(nil)
}

func (o *ErrnoResult) WithError(err error) src.Result {
	o.Data = nil
	o.DataType = src.DataTypeError

	if err != nil {
		if v, ok := err.(src.ErrorGetter); ok {
			o.str, o.htm = false, false
			o.Errno = v.Code()
			o.Error = v.Message()
			return o
		}

		return o.WithCodeError(src.DefaultCodeInternal, err.Error())
	}

	return o.WithCodeError(src.DefaultCodeUnknown, src.DefaultCodeUnknownMessage)
}

func (o *ErrnoResult) WithHtml(body []byte) src.Result {
	o.str, o.htm = false, true
	o.Data = body
	return o
}

func (o *ErrnoResult) WithList(items any) src.Result {
	if items == nil {
		items = []any{}
	}

	o.str, o.htm = false, false
	o.Data = items
	o.DataType = src.DataTypeList
	o.Errno = errnoSuccess
	o.Error = errnoSuccessText
	return o
}

func (o *ErrnoResult) WithPaging(items any, total int64, page, size int) src.Result {
	o.str, o.htm = false, false
	o.Data = src.NewPaginator(items, total, page, size)
	o.DataType = src.DataTypePaging
	o.Errno = errnoSuccess
	o.Error = errnoSuccessText
	return o
}

func (o *ErrnoResult) WithString(str string) src.Result {
	o.htm, o.str = false, true
	o.Data = str
	return o
}
